home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / oldwish / wishSelect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-01-11  |  16.3 KB  |  626 lines

  1. /* 
  2.  * wishSelect.c --
  3.  *
  4.  *    Routines for selection of listed files and groups.
  5.  *
  6.  * Copyright 1987 Regents of the University of California
  7.  * All rights reserved.
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /a/newcmds/wish/RCS/wishSelect.c,v 1.4 89/01/11 11:58:41 mlgray Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21.  
  22. #include "sx.h"
  23. #include "string.h"
  24. #include "wishInt.h"
  25.  
  26. /*
  27.  * Forward references for procedures defined below.
  28.  */
  29. extern    void    WishSelChange();
  30. extern    int    WishSelFetch();
  31.  
  32.  
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * WishChangeSelection --
  37.  *
  38.  *    Change the selection variable.
  39.  *
  40.  * Results:
  41.  *    None.
  42.  *
  43.  * Side effects:
  44.  *    The selection variable is modified.
  45.  *
  46.  *----------------------------------------------------------------------
  47.  */
  48. void
  49. WishChangeSelection(aWindow, clientData, fileP, lineP, addToP)
  50.     WishWindow    *aWindow;
  51.     ClientData        clientData;
  52.     Boolean        fileP;    /* selecting a file or a group? */
  53.     Boolean        lineP;    /* select a whole line, or just file name? */
  54.     Boolean        addToP;    /* just change sel. status of one entry */
  55. {
  56.     WishFile    *filePtr;
  57.     WishGroup    *groupPtr;
  58.     WishSelection    *selPtr, *backPtr;
  59.  
  60.     if (fileP) {
  61.     filePtr = (WishFile *) clientData;
  62.     } else {
  63.     groupPtr = (WishGroup *) clientData;
  64.     }
  65.  
  66.     if (lineP) {
  67.     aWindow->notifierP = TRUE;
  68.     Sx_Notify(wishDisplay, aWindow->surroundingWindow, -1, -1, 0,
  69.         "Line-mode selection temporarily disabled.",
  70.         NULL, TRUE, "Continue", (char *) NULL);
  71.     aWindow->notifierP = FALSE;
  72.     return;
  73.     }
  74.     
  75.     if (fileP) {
  76.     if (!addToP) {
  77.         if (filePtr->selectedP && !lineP) {
  78.         WishClearWholeSelection(aWindow);
  79.         return;
  80.         } else {        /* make the new selection */
  81.         /* check if it's already selected and needs lineP changed. */
  82.         if (filePtr->selectedP == TRUE) {
  83. #ifdef NOTDEF
  84.             for (selPtr = aWindow->selectionList; selPtr != NULL;
  85.                 selPtr = selPtr->nextPtr) {
  86.             if (selPtr->selected.filePtr == filePtr) {
  87.                 break;
  88.             }
  89.             }
  90.             if (selPtr == NULL) {
  91.             sprintf(wishErrorMsg, "%s%s%s", "The selected file `",
  92.                 filePtr->name,
  93.                 "' couldn't be found on the selection list.");
  94.             Sx_Panic(wishDisplay, wishErrorMsg);
  95.             }
  96.             filePtr->lineP = lineP;
  97.             selPtr->lineP = lineP;
  98.             WishRedrawFile(aWindow, filePtr);
  99.             return;
  100. #endif NOTDEF
  101.         }
  102.         /* new selection */
  103.         WishClearWholeSelection(aWindow);
  104.         /*
  105.          * After the first time, Sx_SelectionSet will call
  106.          * WishSelChange, which calls WishClearWholeSelection().
  107.          * This is a warning...
  108.          */
  109.         Sx_SelectionSet(wishDisplay, WishSelFetch, WishSelChange,
  110.             (ClientData) aWindow);
  111.         Tcl_SetVar(aWindow->interp, "sel", filePtr->name, 1);
  112.         Tcl_SetVar(aWindow->interp, "selection", filePtr->name, 1);
  113.         filePtr->selectedP = TRUE;
  114.         selPtr = (WishSelection *)
  115.             malloc(sizeof (WishSelection));
  116.         selPtr->fileP = TRUE;
  117.         selPtr->selected.filePtr = filePtr;
  118.         selPtr->nextPtr = NULL;
  119.         if (lineP) {
  120.             filePtr->lineP = TRUE;
  121.             selPtr->lineP = TRUE;
  122.         } else {
  123.             selPtr->lineP = FALSE;
  124.         }
  125.         if (aWindow->selectionList != NULL) {
  126.             sprintf(wishErrorMsg,
  127.                 "Selection list should have been null and wasn't.");
  128.             Sx_Panic(wishDisplay, wishErrorMsg);
  129.         }
  130.         aWindow->selectionList = selPtr;
  131.         WishRedrawFile(aWindow, filePtr);
  132.         }
  133.         return;
  134.     }
  135.     /* addToP is TRUE */
  136.     if (filePtr->selectedP && !lineP) {
  137.         char    *tclSel;
  138.         char    *removeEntry;
  139.  
  140.         filePtr->selectedP = FALSE;
  141.         filePtr->lineP = FALSE;
  142.         tclSel = Tcl_GetVar(aWindow->interp, "sel", 1);
  143.         if (tclSel == NULL) {
  144.         sprintf(wishErrorMsg, "Tcl selection variable wasn't found.");
  145.         Sx_Panic(wishDisplay, wishErrorMsg);
  146.         }
  147.         removeEntry = (char *) malloc(strlen(tclSel) + 1);
  148.         removeEntry[0] = '\0';
  149.         /* remove it from selection */
  150.         for (selPtr = aWindow->selectionList, backPtr = selPtr;
  151.             selPtr != NULL; selPtr = selPtr->nextPtr) {
  152.         if (!selPtr->fileP) {
  153.             backPtr = selPtr;
  154.             continue;
  155.         }
  156.         if (selPtr->selected.filePtr != filePtr) {
  157.             strcat(removeEntry, filePtr->name);
  158.             strcat(removeEntry, " ");
  159.             backPtr = selPtr;
  160.             continue;
  161.         }
  162.         /* check if nothing is selected anymore */
  163.         if (selPtr == aWindow->selectionList) {
  164.             aWindow->selectionList = selPtr->nextPtr;
  165.         } else {
  166.             backPtr->nextPtr = selPtr->nextPtr;
  167.         }
  168.         free(selPtr);
  169.         WishRedrawFile(aWindow, filePtr);
  170.         break;
  171.         }
  172.         if (removeEntry[strlen(removeEntry) - 1] == ' ') {
  173.         removeEntry[strlen(removeEntry) - 1] = '\0';
  174.         }
  175.         Tcl_SetVar(aWindow->interp, "sel", removeEntry, 1);
  176.         Tcl_SetVar(aWindow->interp, "selection", removeEntry, 1);
  177.         free(removeEntry);
  178.     } else {
  179.         char    *tclSel;
  180.         char    *addEntry;
  181.  
  182.         /* add it to selection */
  183.         /* check if it's already selected and needs lineP changed. */
  184.         if (filePtr->selectedP == TRUE) {
  185. #ifdef NOTDEF
  186.         for (selPtr = aWindow->selectionList; selPtr != NULL;
  187.             selPtr = selPtr->nextPtr) {
  188.             if (selPtr->selected.filePtr == filePtr) {
  189.             break;
  190.             }
  191.         }
  192.         if (selPtr == NULL) {
  193.             sprintf(wishErrorMsg, "%s%s%s", "The selected file `",
  194.                 filePtr->name,
  195.                 "' couldn't be found on the selection list.");
  196.             Sx_Panic(wishDisplay, wishErrorMsg);
  197.         }
  198.         filePtr->lineP = lineP;
  199.         selPtr->lineP = lineP;
  200.         WishRedrawFile(aWindow, filePtr);
  201.         return;
  202. #endif NOTDEF
  203.         }
  204.         /* add new selection */    
  205.         filePtr->selectedP = TRUE;
  206.         if (lineP) {
  207.         filePtr->lineP = TRUE;
  208.         }
  209.         selPtr = (WishSelection *) malloc(sizeof (WishSelection));
  210.         selPtr->fileP = TRUE;
  211.         if (lineP) {
  212.         selPtr->lineP = TRUE;
  213.         } else {
  214.         selPtr->lineP = FALSE;
  215.         }
  216.         selPtr->nextPtr = NULL;
  217.         selPtr->selected.filePtr = filePtr;
  218.         if (aWindow->selectionList == NULL) {
  219.         /*
  220.          * After the first time, Sx_SelectionSet will call
  221.          * WishSelChange, which calls WishClearWholeSelection().
  222.          * This is a warning...
  223.          */
  224.         Sx_SelectionSet(wishDisplay, WishSelFetch, WishSelChange,
  225.             (ClientData) aWindow);
  226.         aWindow->selectionList = selPtr;
  227.         } else {
  228.         for (backPtr = aWindow->selectionList; backPtr->nextPtr != NULL;
  229.             backPtr = backPtr->nextPtr) {
  230.             /* do nothing */
  231.         }
  232.         backPtr->nextPtr = selPtr;
  233.         }
  234.         tclSel = Tcl_GetVar(aWindow->interp, "sel", 1);
  235.         /* space for 2 strings, blank between and null char */
  236.         addEntry = (char *) malloc(strlen(tclSel) +
  237.             strlen(filePtr->name + 2));
  238.         addEntry[0] = '\0';
  239.         strcat(addEntry, tclSel);
  240.         strcat(addEntry, " ");
  241.         strcat(filePtr->name, tclSel);
  242.         Tcl_SetVar(aWindow->interp, "sel", addEntry, 1);
  243.         Tcl_SetVar(aWindow->interp, "selection", addEntry, 1);
  244.         free(addEntry);
  245.         WishRedrawFile(aWindow, filePtr);
  246.         return;
  247.     }
  248.     } else {        /* group selection instead of file selection. */
  249.     /* I don't do tcl selection variable stuff with groups yet. */
  250.     /* lineP stuff doesn't make sense with groups. */
  251.     if (groupPtr->selectedP) {
  252.         /* remove it from selection */
  253.         groupPtr->selectedP = FALSE;
  254.         for (selPtr = aWindow->selectionList, backPtr = selPtr;
  255.             selPtr != NULL; selPtr = selPtr->nextPtr) {
  256.         if (selPtr->fileP) {
  257.             backPtr = selPtr;
  258.             continue;
  259.         }
  260.         if (selPtr->selected.groupPtr != groupPtr) {
  261.             backPtr = selPtr;
  262.             continue;
  263.         }
  264.         /* check if nothing is selected anymore */
  265.         if (selPtr == aWindow->selectionList) {
  266.             aWindow->selectionList = selPtr->nextPtr;
  267.             if (aWindow->selectionList == NULL) {
  268.             /*
  269.              * After the first time, Sx_SelectionSet will call
  270.              * WishSelChange, which calls WishClearWholeSelection().
  271.              * This is a warning...
  272.              */
  273.             Sx_SelectionSet(wishDisplay, WishSelFetch,
  274.                 WishSelChange, (ClientData) aWindow);
  275.             }
  276.         } else {
  277.             backPtr->nextPtr = selPtr->nextPtr;
  278.         }
  279.         free(selPtr);
  280.         /* not yet implemented */
  281.         WishRedrawGroup(aWindow, groupPtr);
  282.         break;
  283.         }
  284.     } else {
  285.         /* add it to selection */
  286.         groupPtr->selectedP = TRUE;
  287.         selPtr = (WishSelection *) malloc(sizeof (WishSelection));
  288.         selPtr->fileP = FALSE;
  289.         selPtr->lineP = FALSE;
  290.         selPtr->nextPtr = NULL;
  291.         selPtr->selected.groupPtr = groupPtr;
  292.         if (aWindow->selectionList == NULL) {
  293.         if (aWindow->selectionList == NULL) {
  294.             /*
  295.              * After the first time, Sx_SelectionSet will call
  296.              * WishSelChange, which calls WishClearWholeSelection().
  297.              * This is a warning...
  298.              */
  299.             Sx_SelectionSet(wishDisplay, WishSelFetch,
  300.                 WishSelChange, (ClientData) aWindow);
  301.         }
  302.         aWindow->selectionList = selPtr;
  303.         } else {
  304.         for (backPtr = aWindow->selectionList; backPtr->nextPtr != NULL;
  305.             backPtr = backPtr->nextPtr) {
  306.             /* do nothing */
  307.         }
  308.         backPtr->nextPtr = selPtr;
  309.         }
  310.         /* not yet implemented */
  311.         WishRedrawGroup(aWindow, groupPtr);
  312.     }
  313.     }
  314.  
  315.     return;
  316. }
  317.  
  318.  
  319.  
  320. /*
  321.  *----------------------------------------------------------------------
  322.  *
  323.  * WishClearWholeSelection --
  324.  *
  325.  *    Empty the selection.
  326.  *
  327.  * Results:
  328.  *    None.
  329.  *
  330.  * Side effects:
  331.  *    The selection list disappears.
  332.  *
  333.  *----------------------------------------------------------------------
  334.  */
  335. void
  336. WishClearWholeSelection(aWindow)
  337.     WishWindow    *aWindow;
  338. {
  339.     WishSelection    *selPtr, *nextPtr;
  340.  
  341.     for (selPtr = aWindow->selectionList; selPtr != NULL; ) {
  342.     if (selPtr->fileP) {
  343.         selPtr->selected.filePtr->selectedP = FALSE;
  344.         selPtr->selected.filePtr->lineP = FALSE;
  345.         WishRedrawFile(aWindow, selPtr->selected.filePtr);
  346.     } else {
  347.         selPtr->selected.groupPtr->selectedP = FALSE;
  348.         /* not yet implemented */
  349.         WishRedrawGroup(aWindow, selPtr->selected.groupPtr);
  350.     }
  351.     nextPtr = selPtr->nextPtr;
  352.     free(selPtr);
  353.     selPtr = nextPtr;
  354.     }
  355.     aWindow->selectionList = NULL;
  356.     Tcl_SetVar(aWindow->interp, "sel", "", 1);
  357.     Tcl_SetVar(aWindow->interp, "selection", "", 1);
  358.  
  359.     return;
  360. }
  361.  
  362.  
  363. /*
  364.  *----------------------------------------------------------------------
  365.  *
  366.  * WishSelFetch --
  367.  *
  368.  *    Called by the Sx selection package when someone wants to know
  369.  *    what's selected.
  370.  *
  371.  * Results:
  372.  *    The number of bytes in the fetched selection, or -1 if there's an error.
  373.  *    (See the Sx_SelectionGet() documentation.)
  374.  *
  375.  * Side effects:
  376.  *    None.
  377.  *
  378.  *----------------------------------------------------------------------
  379.  */
  380. /*ARGSUSED*/
  381. int
  382. WishSelFetch(clientData, askedFormat, firstByte, numBytes, valuePtr,
  383.     formatPtr)
  384.     ClientData    clientData;
  385.     char    *askedFormat;
  386.     int        firstByte;
  387.     int        numBytes;
  388.     char    *valuePtr;
  389.     char    *formatPtr;
  390. {
  391.     WishWindow    *aWindow;
  392.     int            number, n;
  393.     char        *space = NULL;
  394.     char        *copyString;
  395.     WishSelection    *tmpPtr;
  396.  
  397.     /* Use aWindow as the clientData */
  398.     aWindow = (WishWindow *) clientData;
  399.     strncpy(formatPtr, "text", SX_FORMAT_SIZE);
  400.     if (numBytes < 1) {
  401.     return 0;
  402.     }
  403.     if (firstByte < 0) {
  404.     return -1;
  405.     }
  406.     valuePtr[0] = '\0';
  407.  
  408.     /*
  409.      * temporary lunacy test - set number 1 less than numBytes for null char.
  410.      * this fixes stack-trashing problem, but i don't see below where I'm
  411.      * writing off the end of the buffer...
  412.      */
  413.     number = numBytes - 1;
  414.     for (tmpPtr = aWindow->selectionList; tmpPtr != NULL && number > 0;
  415.         tmpPtr = tmpPtr->nextPtr) {
  416.     Boolean    endP = FALSE;
  417.  
  418.     if (!(tmpPtr->selected.filePtr->selectedP)) {
  419.         Sx_Panic(wishDisplay,
  420.             "Inconsistency in selected list discovered.");
  421.     }
  422.     /*
  423.      * Here I'm assuming that if a group is selected, it won't mean
  424.      * to go through and grab all the files...  Maybe it can mean the
  425.      * matching rule or something?  Maybe I need some other selection
  426.      * mechanism for internal group selection?  Or maybe selecting a
  427.      * group is just an interface for actual selection of all the
  428.      * files in it...
  429.      */
  430.     if (!(tmpPtr->fileP)) {
  431.         Sx_Panic(wishDisplay, "Can't fetch group selections yet.");
  432.     }
  433.     if (tmpPtr->nextPtr == NULL) {
  434.         endP = TRUE;
  435.     }
  436.     if (tmpPtr->lineP) {
  437.         int    i;
  438.  
  439.         /*
  440.          * This is how it's done in WishRedrawFile() and
  441.          * the column width calculator, but the calculation should
  442.          * be centralized!
  443.          */
  444.         if (space == NULL) {
  445.         space = (char *) malloc(aWindow->maxEntryWidth + 1);
  446.         }
  447.         strcpy(space, tmpPtr->selected.filePtr->name);
  448.         for (i = strlen(space); i < aWindow->maxEntryWidth + 1;
  449.             i++) {
  450.         space[i] = ' ';
  451.         }
  452.         /*
  453.          * Put in null char so WishGetFileFields concatenates correctly
  454.          * at space[aWindow->maxNameLength + 2].  The 2 is for spaces
  455.          * between the name and info fields.  (Again, from
  456.          * WishRedrawFile().)
  457.          */
  458.         space[aWindow->maxNameLength + 2] = '\0';
  459.         WishGetFileFields(aWindow, tmpPtr->selected.filePtr,
  460.             &(space[aWindow->maxNameLength + 2]));
  461.         copyString = space;
  462.         n = aWindow->maxEntryWidth;
  463.     } else {
  464.         copyString = tmpPtr->selected.filePtr->name;
  465.         n = strlen(copyString);
  466.     }
  467.  
  468.     if (firstByte > 0) {
  469.         if (n <= firstByte) {
  470.         firstByte -= n;
  471.         if (!endP) {        /* for space between strings */
  472.             firstByte--;    /* may leave firstByte -= for space */
  473.         }
  474.         continue;
  475.         } else {
  476.         copyString = copyString + firstByte;
  477.         n -= firstByte;
  478.         firstByte = 0;
  479.         }
  480.     } else if (firstByte < 0) {
  481.         /* firstByte is -1 to show we must first copy a space */
  482.         number--;
  483.         firstByte = 0;
  484.         strcat(valuePtr, " ");
  485.     }
  486.     strncat(valuePtr, copyString, number);
  487.     if (number - n < 0) {
  488.         number = 0;
  489.         break;
  490.     }
  491.     number -= n;
  492.     if (number > 0 && !endP) {
  493.         strcat(valuePtr, " ");
  494.         number--;
  495.     }
  496.     }
  497.     if (space != NULL) {
  498.     free(space);
  499.     space = NULL;
  500.     }
  501.  
  502. /* temporary lunacy, -1 to avoid counting null char if not at end of buffer */
  503.     if (number == 0) {
  504.     return (numBytes - number);
  505.     } else {
  506.     return (numBytes - number - 1);
  507.     }
  508. }
  509.  
  510.  
  511.  
  512. /*
  513.  *----------------------------------------------------------------------
  514.  *
  515.  * WishSelChange --
  516.  *
  517.  *    Called by the Sx selection package whenever the selection changes
  518.  *    out from under us.
  519.  *
  520.  * Results:
  521.  *    None.
  522.  *
  523.  * Side effects:
  524.  *    The list of selected nodes is cleared.
  525.  *
  526.  *----------------------------------------------------------------------
  527.  */
  528. void
  529. WishSelChange(clientData)
  530.     ClientData    clientData;
  531. {
  532.     WishWindow    *aWindow;
  533.  
  534.     aWindow = (WishWindow *) clientData;
  535.     WishClearWholeSelection(aWindow);
  536.  
  537.     return;
  538. }
  539.  
  540.  
  541. /*
  542.  *----------------------------------------------------------------------
  543.  *
  544.  * WishHighlightMovement
  545.  *
  546.  *    Highlight mouse movement to show what file the cursor is over.
  547.  *
  548.  * Results:
  549.  *    None.
  550.  *
  551.  * Side effects:
  552.  *    The display changes.
  553.  *
  554.  *----------------------------------------------------------------------
  555.  */
  556. void
  557. WishHighlightMovement(window, eventPtr)
  558.     Window        window;
  559.     XPointerMovedEvent    *eventPtr;
  560. {
  561.     WishFile    *filePtr;
  562.     WishFile    *last_filePtr = NULL;
  563.     static    int    oldx = -1;    /* Coordinates outside window. */
  564.     static    int    oldy = -1;
  565.     int        x, y;
  566.     WishWindow    *aWindow;
  567.  
  568.     if (eventPtr->type != MotionNotify && eventPtr->type != LeaveNotify) {
  569.     return;
  570.     }
  571.     if (XFindContext(wishDisplay, window, wishWindowContext,
  572.         (caddr_t) &aWindow) != 0) {
  573.     Sx_Panic(wishDisplay, "Fstree didn't recognize given window.");
  574.     }
  575.  
  576.     /* event was selected in display window, so coordinates are ok */
  577.     x = ((XButtonEvent *) eventPtr)->x;
  578.     y = ((XButtonEvent *) eventPtr)->y;
  579.  
  580.     if (eventPtr->type != LeaveNotify) {
  581.     filePtr = WishMapCoordsToFile(aWindow, x, y);
  582.     } else {
  583.     filePtr = NULL;
  584.     }
  585.     last_filePtr = WishMapCoordsToFile(aWindow, oldx, oldy);
  586.  
  587.     if (filePtr == last_filePtr) {    /* leave highlighting alone */
  588.     oldx = x;
  589.     oldy = y;
  590.     return;
  591.     }
  592.     
  593.     /*
  594.      * If we've already toggled a node before, re-toggle it to turn it off
  595.      * as we move away from it.
  596.      */
  597.     if (last_filePtr != NULL) {
  598.     /* I used to toggle highlighting here rather than just turn it off. */
  599.     last_filePtr->highlightP = FALSE;
  600.     WishRedrawFile(aWindow, last_filePtr);
  601.     oldx = oldy = -1;    /* Set to coordinates outside window */
  602.     }
  603.  
  604.     /*
  605.      * If no new file, do nothing.
  606.      */
  607.     if (filePtr == NULL) {
  608.     return;
  609.     }
  610.  
  611.  
  612.     /*
  613.      * toggle new file.
  614.      */
  615.     /*
  616.      * I used to toggle highlighting here rather than just turn it on,
  617.      * but now I don't do selection by toggling, so I needn't here either.
  618.      */
  619.     filePtr->highlightP = TRUE;
  620.     WishRedrawFile(aWindow, filePtr);
  621.     oldx = x;
  622.     oldy = y;
  623.  
  624.     return;
  625. }
  626.